import React, {
  useMemo,
  useCallback,
  cloneElement,
  useContext,
  useState,
} from 'react';
import { observer } from 'mobx-react-lite';
import {
  Page, Content, Header, HeaderButtons, Breadcrumb,
  axios, CONSTANTS,
} from '@choerodon/master';
import { Tabs, message } from 'choerodon-ui';
import { useModal } from 'choerodon-ui/pro';
import map from 'lodash/map';
import classNames from 'classnames';
import { get } from '@choerodon/inject';
import { isEmpty } from 'lodash';
import { useRouteMatch, useHistory, useLocation } from 'react-router';
import TemplateSave from './components/template-save';
import { useAppPipelineEditStore } from './stores';
import {
  TAB_ADVANCE_SETTINGS, TAB_BASIC, TAB_CI_CONFIG, TAB_FLOW_CONFIG,
} from './stores/CONSTANTS';
import PipelineBasicInfo from './components/pipeline-basic-info';
import StagesEdits from './components/stage-edits';
import CiVariasConfigs from './components/ci-varias-configs';
import PipelineAdvancedConfig from './components/pipeline-advanced-config';
import { TabkeyTypes } from '../../interface';
import useTabData from './hooks/useTabData';
import usePipelineContext from '../../hooks/usePipelineContext';
import { handleTabDataValidate } from './services/handleTabsDataValidate';
import { handleTabDataTransform } from './services/handleTabDataTransform';
import { ciCdPipelineApi } from '@/api/cicd-pipelines';
import { ciTemplatePipelineApi } from '@/api/ci-template-pipeline';

const { TabPane } = Tabs;

const submitInstall = get('configuration.devops-routes-app-pipeline-pipelineEdit:submit');

const create = submitInstall?.create;

const transformResponse = submitInstall?.transformResponse;

const AppPipelineEdit = () => {
  const {
    prefixCls,
    formatAppPipelineEdit,
    formatCommon,
    currentKey,
    setTabKey,
    type = 'create',
    tabsData,
    AppState,
  } = useAppPipelineEditStore();

  const [submitLoading, setSubmitLoading] = useState(false);

  const createForm = get('configuration.devops-routes-app-pipeline-pipelinCreate:createForm');

  const transformSubmitBasic = get('configuration.devops-routes-app-pipeline-pipelineBasicInfo:transformSubmit');

  const Modal = useModal();

  const {
    basicInfo,
    level,
    onSave,
    onCreate,
  } = usePipelineContext();

  const {
    params: {
      id,
    },
  } = useRouteMatch<any>();

  const history = useHistory();

  const {
    pathname,
    search,
  } = useLocation();

  const contentCls = classNames(`${prefixCls}-content`, {
    [`${prefixCls}-content-bgnone`]: TAB_FLOW_CONFIG === currentKey,
  });

  const getBasicInfo = () => {
    const tempObj: Record<string, JSX.Element> = {
    };
    if (basicInfo && !isEmpty(basicInfo)) {
      const { Component } = basicInfo;
      tempObj[TAB_BASIC] = cloneElement(Component, { useTabData });
    } else {
      tempObj[TAB_BASIC] = <PipelineBasicInfo />;
    }
    return tempObj;
  };

  const tabsCompoents: Record<string, JSX.Element> = {
    ...getBasicInfo(),
    [TAB_FLOW_CONFIG]: <StagesEdits />,
    [TAB_CI_CONFIG]: <CiVariasConfigs />,
    [TAB_ADVANCE_SETTINGS]: <PipelineAdvancedConfig level={level} />,
  };

  const handleTabChange = (value: TabkeyTypes) => setTabKey(value);

  /**
   * 项目层的处理提交的事件
   */
  const handleSumitWhileProjectCreate = async (
    tData: any,
    setFunc: any,
    exData: any,
    // 是否是流水线中的保存为流水线模板
    isSaveTemplate: any,
  // eslint-disable-next-line consistent-return
  ) => {
    if (window.location.href.includes('project-pipeline-template')) {
      if (onCreate) {
        await onCreate(tabsData);
        setSubmitLoading(false);
      } else {
        setSubmitLoading(false);
      }
    } else {
      setSubmitLoading(true);
      // eslint-disable-next-line consistent-return
      const finalFunc = async () => {
        let finalData = handleTabDataTransform(tabsData, transformSubmitBasic);
        finalData = {
          ...finalData,
          ...exData || {},
        };
        if (isSaveTemplate) {
          // 如果是保存为流水线模板 要修改一些字段名
          finalData = {
            ...finalData,
            templateStageVOS: finalData.devopsCiStageVOS.map((i: any) => {
              // eslint-disable-next-line no-param-reassign
              i.ciTemplateJobVOList = i.jobList;
              return i;
            }),
          };
          try {
            const flag = await ciTemplatePipelineApi.saveTemplate(finalData);
            if (flag?.failed) {
              return false;
            }
            return flag;
          } catch (error) {
            return false;
            console.log(error);
          }
        } else {
          try {
            const res = create
              ? await axios(create?.config(finalData, AppState))
              : await ciCdPipelineApi.handlePipelineCreate(finalData);
            setSubmitLoading(false);
            if (res && res.failed) {
              return false;
            }
            history.go(-1);
          } catch (error) {
            console.log(error);
            setSubmitLoading(false);
          }
        }
      };
      if (!createForm) {
        const { isValidated, key, reason } = handleTabDataValidate(tabsData, type);
        if (isValidated) {
          finalFunc();
        } else {
          key && setTabKey(key);
          reason && message.error(reason);
          setSubmitLoading(false);
          return false;
        }
      } else {
        finalFunc();
      }
    }
  };

  const transData = (data: any) => {
    const newData = data;
    if (newData?.devopsCdStageVOS) {
      newData.devopsCdStageVOS = newData.devopsCdStageVOS.map((i: any) => {
        if (i?.jobList && i?.jobList?.length > 0) {
          // eslint-disable-next-line
          i.jobList = i.jobList.map((j: any) => {
            if (j.triggerValue) {
              // eslint-disable-next-line
              j.triggerValue = j.triggerValue.replace(/^(\s|,)+|(\s|,)+$/g, '');
            }
            return j;
          });
        }
        return i;
      });
    }
    return newData;
  };

  /**
   * 项目层的编辑
   */
  const handleSumitWhileProjectEdit = async (
    tData: any,
    setFunc: any,
    exData: any,
    // 是否是流水线中的保存为流水线模板
    isSaveTemplate: any,
  // eslint-disable-next-line consistent-return
  ) => {
    setSubmitLoading(true);
    const { isValidated, key, reason } = handleTabDataValidate(tabsData, type);
    if (isValidated) {
      if (window.location.href.includes('project-pipeline-template')) {
        if (onSave) {
          await onSave(tabsData);
          setSubmitLoading(false);
        } else {
          setSubmitLoading(false);
        }
      } else {
        let finalData = transData(handleTabDataTransform(tabsData));
        finalData = {
          ...finalData,
          ...exData || {},
        };
        if (isSaveTemplate) {
          // 如果是保存为流水线模板 要修改一些字段名
          finalData = {
            ...finalData,
            templateStageVOS: finalData.devopsCiStageVOS.map((i: any) => {
              // eslint-disable-next-line no-param-reassign
              i.ciTemplateJobVOList = i.jobList;
              return i;
            }),
          };
          try {
            const flag = await ciTemplatePipelineApi.saveTemplate(finalData);
            setSubmitLoading(false);

            if (flag?.failed) {
              return false;
            }
            return flag;
          } catch (error) {
            setSubmitLoading(false);
            return false;
            console.log(error);
          }
        } else {
          try {
            const res = await ciCdPipelineApi.handlePipelineModify(id, finalData);
            setSubmitLoading(false);
            if (res && res.failed) {
              return false;
            }
            history.push({
              pathname: '/devops/pipeline-manage',
              search: `${search}&pipelineId=${id}`,
            });
          } catch (error) {
            setSubmitLoading(false);
            throw new Error(error);
          }
        }
      }
    } else {
      key && setTabKey(key);
      reason && message.error(reason);
      setSubmitLoading(true);
      // eslint-disable-next-line consistent-return
      return false;
    }
  };

  const submitMapWhileCreate: Record<'project' | 'site' | 'organization', Function | undefined> = {
    project: handleSumitWhileProjectCreate,
    site: onCreate,
    organization: onCreate,
  };

  const submitMapWhileEdit: Record<'project' | 'site' | 'organization', Function | undefined> = {
    project: handleSumitWhileProjectEdit,
    site: onSave,
    organization: onSave,
  };

  const handleSubmit = async ({
    // 这是额外给finalData的数据 比如保存为流水线模板贼是把templateSaveDs的数据 给覆盖上去
    extraData,
    isSaveTemplate = false,
  }: any) => {
    // 这里是提交的时候 如果高级设置的认证管理表单都清空了 就把数据里的ciDockerAuthConfigDTOList全部清空 避免只把表单上的数据清了 本身数据带有的id等字段还在
    if (tabsData[TAB_ADVANCE_SETTINGS]?.ciDockerAuthConfigDTOList
      && tabsData[TAB_ADVANCE_SETTINGS]?.ciDockerAuthConfigDTOList.length > 0) {
      tabsData[TAB_ADVANCE_SETTINGS].ciDockerAuthConfigDTOList = tabsData[TAB_ADVANCE_SETTINGS]
        ?.ciDockerAuthConfigDTOList.filter((i: any) => i.domain) || [];
    } else {
      tabsData[TAB_ADVANCE_SETTINGS].ciDockerAuthConfigDTOList = [];
    }
    if (['create', 'copy'].includes(type)) {
      return level && submitMapWhileCreate[level]?.(tabsData, setTabKey, extraData, isSaveTemplate);
    }
    return level && submitMapWhileEdit[level]?.(tabsData, setTabKey, extraData, isSaveTemplate);
  };

  const handleSaveToTemplate = () => {
    Modal.open({
      title: '保存为流水线模板',
      style: {
        width: CONSTANTS.MODAL_WIDTH.MIDDLE,
      },
      children: (
        <TemplateSave
          handleSubmit={handleSubmit}
          level={level}
        />
      ),
      drawer: true,
    });
  };

  /** @type {*} 头部按钮 */
  const headerItems = useMemo(() => ([
    {
      disabled: submitLoading,
      loading: submitLoading,
      handler: handleSubmit,
      name: formatCommon({ id: 'save' }),
      icon: 'check',
    },
    {
      permissions: ['choerodon.code.project.develop.ci-pipeline.ps.saveToTemplate'],
      // disabled: submitLoading,
      // loading: submitLoading,
      name: '保存为模板',
      icon: 'save',
      display: level === 'project' && !window.location.href.includes('project-pipeline-template'),
      handler: handleSaveToTemplate,
    },
    {
      handler: () => {
        if (window.location.href.indexOf('pipeline-manage') !== -1 && id !== 'default') {
          history.push({
            pathname: '/devops/pipeline-manage',
            search: `${search}&pipelineId=${id}`,
          });
        } else {
          const path = {
            pathname: history.location.pathname.split('/edit/edit')[0],
            search: history.location.search,
          };
          history.push(path);
        }
      },
      name: formatCommon({ id: 'cancel' }),
      icon: 'close',
    },
  ]), [handleSubmit]);

  const renderTabHeader = useCallback(() => (
    <Tabs
      className={`${prefixCls}-tabs`}
      activeKey={currentKey}
      onChange={handleTabChange}
    >
      {
        map(tabsCompoents, (_componet, key) => (
          <TabPane tab={formatAppPipelineEdit({ id: key })} key={key} />
        ))
      }
    </Tabs>
  ), [currentKey]);

  /**
   * 根据当前的层级和编辑修改情况渲染title
   * @return {string}
   */
  const renderTitle = () => {
    let title = '';
    if (level === 'project' && !window.location.href.includes('project-pipeline-template')) {
      title = ['create', 'copy'].includes(type) ? '创建流水线' : '修改流水线';
    } else {
      title = type === 'create' ? '创建流水线模板' : '编辑流水线模板';
    }
    return title;
  };

  return (
    <Page className={prefixCls}>
      <Header>
        <HeaderButtons items={headerItems} />
      </Header>
      <Breadcrumb
        title={renderTitle()}
        extraNode={renderTabHeader()}
      />
      <Content className={contentCls}>
        {tabsCompoents[currentKey]}
      </Content>
    </Page>
  );
};

export default observer(AppPipelineEdit);
